#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "main.h"
#include "state.h"
#include "point.h"
#include "util.h"

/*
 * Alokuje nový stav na heapě pro zadanou hloubku.
 */
State *allocateState(int depth){
	State *state = (State *)malloc(sizeof(State));
	if(state == NULL){
    	fprintf(stderr, "Out of memory during allocating new state.\n");
	}
	state->depth = depth;
	if(depth > 0){
		state->statePoints = (Point *)malloc(depth * sizeof(Point));
		if(state->statePoints == NULL){
    		fprintf(stderr, "Out of memory during allocating new state.\n");
		}
	}
	state->value = 0;
	return state;
}

/*
 * Alokuje nový stav na heapě s hloubkou zadaného stavu + 1. Dále zkopíruje
 * stavy z rodičovského stavu do potomka.
 */
State *childState(State *state, int x, int y){
	State *child = allocateState(state->depth + 1);
	child->value = state->value;
	int i;
	for(i = 0; i < state->depth; i++){
		child->statePoints[i] = state->statePoints[i];
	}
	Point *newPoint = &(child->statePoints[state->depth]);
	newPoint->x = x;
	newPoint->y = y;
	int j;
	for(j = 0; j < f; j++){
		child->value += countDistance(fixedPoints[j], *newPoint);
	}
	for(j = 0; j < state->depth; j++){
		child->value += countDistance(state->statePoints[j], *newPoint);
	}
	return child;
}

/*
 * Odstraní stav z heapy.
 */
void freeState(State *state){
	if(state->depth > 0){
		free(state->statePoints);
	}
	free(state);
}

/*
 * Výpíše zadaný stav.
 */
void printState(State *state){
	if(state == NULL){
		printf("Provided state is NULL!");
		return;
	}

	int depthOrder = getOrderOfMagnitude(state->depth);
	int mOrder = getOrderOfMagnitude(m);
	int kOrder = getOrderOfMagnitude(k);
	int index = 0;
	/*
	 * 19 = "State with depth : "
	 * depthOrder = počet znaků v číslicí hloubky stavu
	 * 3 = "[, ]"
	 * mOrder, kOrder = počet znaků v číslici m a k (rozměry plánu, tudíž
	 * 		maximální možné souřadnice)
	 * 2 = konec řádku + NULL znak
	 */
	char *string = (char *)malloc(19 + depthOrder + state->depth * (3 + mOrder + kOrder) + 2);

	index += sprintf(string + index, "State with depth %d: ", state->depth);
	int i;
	for(i = 0; i < state->depth; i++){
		Point point = state->statePoints[i];
		index += sprintf(string + index, "[%d,%d]", point.x, point.y);
	}
	index += sprintf(string + index, "\n");
	string[index] = '\0';

	printf(string);
	free(string);
}
